<?php

// +----------------------------------------------------------------------
// | 合同服务层
// +----------------------------------------------------------------------
// | 主要服务于合同
// +----------------------------------------------------------------------
// | 错误编码头 237xxx
// +----------------------------------------------------------------------
namespace common\service;


use common\model\EntityModel;
use common\model\ProjectModel;
use common\model\TaskModel;
use common\model\UserModel;
use support\ErrorCode;
use support\SingletonTrait;

class ChatService
{

    use  SingletonTrait;

    /**
     * 获得实体聊天会话
     * @param $param
     * @return mixed
     * @throws \Exception
     */
    public function getEntityChat($param)
    {
        $entityId = $param['entity_id'];
        $entity = model(EntityModel::class)->find($entityId);
        return $this->createEntityChat($entity);
    }

    /**
     * 创建实体群聊
     * @param $entity
     * @return mixed
     * @throws \Exception
     */
    public function createEntityChat($entity)
    {
        if (empty($entity)) {
            throw_strack_exception('entity data not found', ErrorCode::ENTITY_NOT_FOUND);
        }
        $taskEntityIds[] = $entity['id'];
        $taskMember[] = $entity['created_by'];
        $moduleCode = module_by_id($entity['module_id']);
        $needModuleCode = ['level', 'asset', 'shot', 'design', 'storyboard', 'sequence'];
        if (isset($entity['json']) && !is_array($entity['json'])) {
            $entity['json'] = json_decode($entity['json'], true);
        }
        // 创建概念和分镜时就会生成群聊，其他的都跳过或者查找上一级是否已经有群聊
        if (!in_array($moduleCode['code'], $needModuleCode)) {
            return null;
        }
        if ($moduleCode['code'] == 'level' || $moduleCode['code'] == 'asset') {
            $entity = model(EntityModel::class)
                ->where(['id' => $entity['json'][$moduleCode['code'] . '_design']])
                ->find();
        } else if ($moduleCode['code'] == 'shot' || $moduleCode['code'] == 'storyboard' || $moduleCode['code'] == 'sequence') {
            // 创建镜头是新建剧集群，需要找到对应的项目下面的对应编码集，群名格式为：项目名+集名
            $entity = model(EntityModel::class)
                ->where(['project_id' => $entity['project_id'], 'module_id' => module_by_code('episode')['id'], 'code' => $entity['initial_episode_code']])
                ->find();
            $project = model(ProjectModel::class)->where(['id' => $entity['project_id']])->find();
            $entity['name'] = $project['name'] . '/' . $entity['name'];
        }
        if (empty($entity['id'])) {
            throw_strack_exception('entity data not found', ErrorCode::ENTITY_NOT_FOUND);
        }
        $entityId = $entity['id'];
        $requestData = ['param' => ['filter' => [
            'link_id' => $entityId,
            'link_type' => "entity",
            'project_id' => $entity['project_id'],
        ]]];
        $chat = teamones_request('teamones-im', 'oauth/find_chat', $requestData)['data'];
        if (empty($chat)) {
            $taskMember = $this->getTaskAllMember($moduleCode, $taskEntityIds, $entity, $taskMember);
            $imUserIds = model(UserModel::class)->where(['id' => ['IN', $taskMember]])->column('union_id');
            $requestData = [
                'data' => [
                    'chat' => [
                        'name' => $entity['name'],
                        'type' => 'group',
                        'project_id' => $entity['project_id'],
                        'link_id' => $entity['id'],
                        'link_type' => 'entity',
                        'from_tenant_id' => $entity['tenant_id'],
                        'created_by' => $entity['created_by'],
                        'edited_at' => time()
                    ],
                    'chat_users' => $imUserIds,
                    'owner' => 0
                ]
            ];
            $chat = teamones_request('teamones-im', 'oauth/create_chat', $requestData)['data'];
        }
        return $chat;
    }

    /**
     * 获取当前用户所在的实体会话
     * @param $param
     * @param $unionId
     * @return array|mixed|\Yurun\Util\YurunHttp\Http\Response
     * @throws \Exception
     */
    public function getCurrentUserEntityChat($param, $unionId)
    {
        $entityId = $param['entity_id'];
        $entity = model(EntityModel::class)->find($entityId);
        $chat = $this->createEntityChat($entity);

        if (empty($chat)) {
            return null;
        }

        //判定当前用户是否在会话,不在则不显示
        $globalId = $chat["global_id"];
        $requestData = [
            "param" => [
                "filter" => [
                    "chat_global_id" => $globalId,
                    "user_id" => $unionId,
                    "is_leave" => "no",
                ]
            ]
        ];
        $result = teamones_request('teamones-im', 'chat_user/find', $requestData);
        if (empty($result["data"])) {
            return null;
        }

        return $chat;
    }

    /**
     * 批量创建群聊
     * @param $entityIds
     * @return array
     * @throws \Exception
     */
    public function selectBatchEntityChat($entityIds)
    {
        $entityList = model(EntityModel::class)
            ->join("module on module.id = entity.module_id")
            ->where(["entity.id" => ["IN", $entityIds]])
            ->field([
                "entity.id", "entity.code", "entity.initial_episode_code", "entity.project_id", "module.code as module_code",
                "JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.',module.code,'_design'))) as design_id"
            ])
            ->select();

        if (empty($entityList)) {
            return [];
        }

        $needModuleCode = ['level', 'asset', 'design', 'shot', 'storyboard', "episode"];

        // 获取群聊需要的 实体id
        $designEntityMap = [];
        $designIds = [];
        $episodeList = [];
        //只查找单项目的
        $projectId = 0;
        $episodeEntityMap = [];
        foreach ($entityList as $entityItem) {
            if (in_array($entityItem["module_code"], $needModuleCode)) {
                if (empty($projectId)) {
                    $projectId = $entityItem["project_id"];
                }

                if (in_array($entityItem["module_code"], ['level', 'asset'])) {
                    $designEntityMap[$entityItem["id"]] = $entityItem["design_id"];
                    $designIds[$entityItem["design_id"]] = $entityItem["design_id"];
                } elseif ($entityItem["module_code"] === "design") {
                    $designIds[$entityItem["id"]] = $entityItem["id"];
                } elseif ($entityItem["module_code"] === "episode") {
                    $episodeList[] = $entityItem;
                } elseif (in_array($entityItem["module_code"], ['shot', 'storyboard'])) {
                    $episodeEntityMap[$entityItem["id"]] = $entityItem["initial_episode_code"];
                }
            }
        }
        $designIds = array_values($designIds);

        $episodeIds = [];
        $episodeCodes = [];
        $episodeCodeIdMap = [];
        foreach ($episodeList as $episodeItem) {
            $episodeCodes[] = $episodeItem['code'];
            $episodeIds[] = $episodeItem['id'];
            $episodeCodeIdMap[$episodeItem['code']] = $episodeItem['id'];
        }

        $episodeEntityIdMap = [];
        if (!empty($episodeEntityMap)) {
            $episodeEntityEpisodeCodes = array_unique(array_values($episodeEntityMap));
            $diffEpisodeCodes = array_diff($episodeEntityEpisodeCodes, $episodeCodes);

            if (!empty($diffEpisodeCodes)) {
                $diffEpisodeCodesList = model(EntityModel::class)->where(["code" => ["IN", $diffEpisodeCodes], "project_id" => $projectId])->field("id,code,project_id,name,tenant_id,created_by")->select();
                if (!empty($diffEpisodeCodesList)) {
                    $diffEpisodeIds = [];
                    foreach ($diffEpisodeCodesList as $diffEpisodeCodesItem) {
                        $diffEpisodeIds[] = $diffEpisodeCodesItem["id"];
                        $episodeCodeIdMap[$diffEpisodeCodesItem["code"]] = $diffEpisodeCodesItem["id"];
                    }
                    $episodeIds = array_merge($episodeIds, $diffEpisodeIds);
                }
            }
        }


        foreach ($episodeEntityMap as $indexEntityId => $episodeEntityMapItem) {
            if (isset($episodeCodeIdMap[$episodeEntityMapItem])) {
                $episodeEntityIdMap[$indexEntityId] = $episodeCodeIdMap[$episodeEntityMapItem];
            } else {
                unset($episodeEntityIdMap[$indexEntityId]);
            }
        }


        $chatEntityIds = array_merge($designIds, $episodeIds);
        if (empty($chatEntityIds)) {
            return [];
        }
        $requestData = [
            "param" => [
                "filter" => [
                    "type" => "group",
                    "project_id" => $projectId,
                    "link_id" => ["-in", join(",", $chatEntityIds)],
                    "link_type" => "entity",
                    "from_tenant_id" => \request()->getTenantId()
                ],
                "fields" => "id,global_id,link_id,type,link_type,from_tenant_id"
            ]
        ];
        $chat = teamones_request('teamones-im', 'chat/select', $requestData)['data'];

        if (empty($chat["rows"])) {
            return [];
        }
        $chat = $chat["rows"];
        $chat = array_column($chat, null, 'link_id');

        $chatEntityData = [];
        foreach ($entityList as $entityItem) {
            if (in_array($entityItem["module_code"], ['level', 'asset'])) {
                if (isset($designEntityMap[$entityItem["id"]]) && isset($chat[$designEntityMap[$entityItem["id"]]])) {
                    $chatEntityData[$entityItem["id"]] = $chat[$designEntityMap[$entityItem["id"]]];
                }
            } elseif (in_array($entityItem["module_code"], ["design", "episode"]) && isset($chat[$entityItem["id"]])) {
                $chatEntityData[$entityItem["id"]] = $chat[$entityItem["id"]];
            } elseif (in_array($entityItem["module_code"], ['shot', 'storyboard'])) {
                if (isset($episodeEntityIdMap[$entityItem["id"]]) && isset($chat[$episodeEntityIdMap[$entityItem["id"]]])) {
                    $chatEntityData[$entityItem["id"]] = $chat[$episodeEntityIdMap[$entityItem["id"]]];
                }
            }
        }
        return $chatEntityData;
    }

    public function inviteChatUser($taskId)
    {
//        $rpcService = UCenterService::getInstance();
//        //  避免缺少执行人 每次都进行邀请用户
//        $tasks = model(TaskModel::class)
//            ->join("entity ON task.entity_id = entity.id")
//            ->where(['task.id' => $taskId])
//            ->where("(task.tenant_id = task.executor_tenant_id or task.executor_tenant_id = 0 ) AND entity.initial_episode_code is not null")
//            ->field("task.id,task.entity_id,task.project_id,task.executor,task.assignee,entity.initial_episode_code,(select id from entity erow where erow.code = entity.initial_episode_code AND erow.project_id = entity.project_id limit 1) as episode_id ")
//            ->select();
//
//
//
//        $tasks = array_column($tasks, null, 'id');
//        $userIdArray = [];
//        foreach ($tasks as $task) {
//
//            if ($task['executor'] == 0) {
//                continue;
//            }
//            $userIdArray[] = $task['executor'];
//            $userIdArray[] = $task['assignee'];
//        }
//        $userIdArray = array_unique($userIdArray);
//        // 用户map id => union_id
//        $userData = model(UserModel::class)->where(['id' => ['IN', implode(',', $userIdArray)]])->field("id,union_id")->select();
//        $userMap = array_column($userData, 'union_id', 'id');
//
//
//        // 替换$userShouldBeChatGroupByEntityId user_id为union_id
//        $userIdArray = array_map(function ($item) use (&$userMap) {
//            return $userMap[$item] ?? 0;
//        }, $userIdArray);
//
//
//        if (count($userIdArray)) {
//            $rpcService->oAuth->inviteChatUser([
//                'data' => [
//                    'chat_global_id' => $chat['global_id'],
//                    'user_id' => $userIdArray,
//                ]
//            ]);
//        }
    }

    /**
     * 推送实体任务消息
     * @param $message
     * @param $chat
     * @return void
     */
    public function pushEntityTaskMessage($message, $chat)
    {
        $data = [
            "data" => [
                'chat' => $chat,
                'chat_message_content' => $message
            ]
        ];
        teamones_request('teamones-im', 'message/push_entity_task_chat_message', $data);
    }

    /**
     * 获取固定的实体任务消息模板
     * @param $message
     * @param $userId
     * @param $entity
     * @param $task
     * @return mixed
     * @throws \think\Exception
     */
    public function getEntityTaskMessageTemplate($message, $userId, $entity, $task = [])
    {
        $operator = model(UserModel::class)->field('id,name,union_id')->where(['id' => $userId])->find();
        $entityName = get_chat_entity_task_name($entity, $task);
        $replace = [
            'operator' => ['id' => $operator['union_id'], 'name' => $operator['name']],
            'entity_name' => $entityName
        ];
        $message['replace'] = isset($message['replace']) ? array_merge($message['replace'], $replace) : $replace;
        return $message;
    }

    /**
     * 获取指定实体下的所有相关任务成员
     * @param $moduleCode
     * @param $taskEntityIds
     * @param $entity
     * @param $taskMember
     * @return array
     */
    private function getTaskAllMember($moduleCode, $taskEntityIds, $entity, $taskMember)
    {
        if ($moduleCode['code'] == 'level' || $moduleCode['code'] == 'asset') {
            $taskEntityIds[] = $entity['id'];
            $taskList = model(TaskModel::class)
                ->field('assignee,executor,assignee_producer')
                ->where(['entity_id' => ['In', $taskEntityIds]])
                ->group('assignee,executor,assignee_producer')
                ->select();
            if ($taskList) {
                foreach ($taskList as $taskItem) {
                    if (!empty($taskItem['assignee']) && $taskItem['assignee'] > 0) {
                        $taskMember[] = $taskItem['assignee'];
                    }
                    if (!empty($taskItem['executor']) && $taskItem['executor'] > 0) {
                        $taskMember[] = $taskItem['assignee'];
                    }
                    if (!empty($taskItem['assignee_producer']) && $taskItem['assignee_producer'] > 0) {
                        $taskMember[] = $taskItem['assignee'];
                    }
                }
                $taskMember = array_unique($taskMember);
            }
        } else if ($moduleCode['code'] == 'shot' || $moduleCode['code'] == 'storyboard') {
            $page = 1;
            while (true) {
                $entityShotList = model(EntityModel::class)
                    ->field('entity.*')
                    ->join('module m on m.id = entity.module_id')
                    ->where(['entity.initial_episode_code' => $entity['initial_episode_code'], 'entity.project_id' => $entity['project_id'], 'm.code' => ['IN', 'shot,storyboard']])
                    ->page($page, 100)
                    ->select();
                if (empty($entityShotList)) {
                    break;
                }
                $entityShotIds = array_column($entityShotList, 'id');
                $taskList = model(TaskModel::class)
                    ->field('assignee,executor,assignee_producer')
                    ->where(['entity_id' => ['In', $entityShotIds]])
                    ->group('assignee,executor,assignee_producer')
                    ->select();
                if ($taskList) {
                    foreach ($taskList as $taskItem) {
                        if (!empty($taskItem['assignee']) && $taskItem['assignee'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                        if (!empty($taskItem['executor']) && $taskItem['executor'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                        if (!empty($taskItem['assignee_producer']) && $taskItem['assignee_producer'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                    }
                }
                $page++;
            }
            $taskMember = array_unique($taskMember);
        } else if ($moduleCode['code'] == 'design') {
            $taskEntityIds = model(EntityModel::class)
                ->where(['project_id' => $entity['project_id'], 'code' => $entity['code'], 'initial_episode_code' => $entity['initial_episode_code']])
                ->column('id');
            if (!empty($taskEntityIds)) {
                $taskList = model(TaskModel::class)
                    ->field('assignee,executor,assignee_producer')
                    ->where(['entity_id' => ['In', $taskEntityIds]])
                    ->group('assignee,executor,assignee_producer')
                    ->select();
                if ($taskList) {
                    foreach ($taskList as $taskItem) {
                        if (!empty($taskItem['assignee']) && $taskItem['assignee'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                        if (!empty($taskItem['executor']) && $taskItem['executor'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                        if (!empty($taskItem['assignee_producer']) && $taskItem['assignee_producer'] > 0) {
                            $taskMember[] = $taskItem['assignee'];
                        }
                    }
                    $taskMember = array_unique($taskMember);
                }
            }
        }
        return $taskMember;
    }
}
